package com.yx.changdao.common.utils;

import com.yx.changdao.common.data.Result;
import com.yx.changdao.common.exception.AlertException;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * word文件导出工具类
 *
 * @author wangzd
 * @createtime 2020/4/30 10:03
 */
public class WordExportUtil {

    private static Logger log = LoggerFactory.getLogger(WordExportUtil.class);

    private WordExportUtil() {
        super();
    }

    // 单例
    private static WordExportUtil instance = null;

    public static WordExportUtil getInstance() {
        if (null == instance) {
            synchronized (WordExportUtil.class) {
                if (null == instance) {
                    instance = new WordExportUtil();
                }
            }
        }
        return instance;
    }

    /**
     * @param templateFilePath 模板文件路径(带模板的文件名 xxxx.ftl)
     * @param dataMap          向模板中传输的值
     * @param exportFilePath   导出文件路径(带文件名)
     * @param loadType         设置路径加载方式。 1-绝对路径 2(非 1 的值)-项目相对路径
     * @return
     * @throws Exception
     */
    public File createDocFile(String templateFilePath, Map<String, Object> dataMap,
                              String exportFilePath, int loadType) throws Exception {
        Template t = null;
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding("UTF-8");

        try {
            templateFilePath = pathReplace(templateFilePath);
            if (!templateFilePath.endsWith(".ftl")) {
                throw new AlertException("文件导出模板路径错误");
            }
            String ftlPath = templateFilePath.substring(0, templateFilePath.lastIndexOf("/"));
            if (loadType == 1) {
                // FTL文件所存在的位置
                configuration.setDirectoryForTemplateLoading(new File(ftlPath));
            } else {
                // 以类加载器的方式查找模板文件路径
                configuration.setClassForTemplateLoading(this.getClass(), ftlPath);
            }
            // ftl文件的文件名
            String ftlFile = templateFilePath.substring(templateFilePath.lastIndexOf("/") + 1);
            t = configuration.getTemplate(ftlFile);

            File outFile = new File(exportFilePath);
            Writer out = null;
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
            t.process(dataMap, out);
            out.close();
        } catch (Exception e) {
            // IOException | TemplateException
            log.error("导出word文档出错", e);
            e.printStackTrace();
            throw e;
        }
        return null;
    }


    /**
     * 指定导出文件的文件名
     *
     * @param templateFilePath
     * @param dataMap
     * @param exportFilePath   导出文件路径，不带文件名
     * @param exportFileName   导出文件的文件名，必须以 .doc 结尾
     * @param loadType
     * @return
     * @throws Exception
     */
    public File createDocFile2(String templateFilePath, Map<String, Object> dataMap,
                               String exportFilePath, String exportFileName, int loadType) throws Exception {
        Template t = null;
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding("UTF-8");

        try {
            templateFilePath = pathReplace(templateFilePath);
            if (!templateFilePath.endsWith(".ftl")) {
                throw new AlertException("文件导出模板路径错误");
            }
            String ftlPath = templateFilePath.substring(0, templateFilePath.lastIndexOf("/"));
            if (loadType == 1) {
                // FTL文件所存在的位置
                configuration.setDirectoryForTemplateLoading(new File(ftlPath));
            } else {
                // 以类加载器的方式查找模板文件路径
                configuration.setClassForTemplateLoading(this.getClass(), ftlPath);
            }
            // ftl文件的文件名
            String ftlFile = templateFilePath.substring(templateFilePath.lastIndexOf("/") + 1);
            t = configuration.getTemplate(ftlFile);

            if (!exportFilePath.endsWith("\\")) {
                throw new AlertException("导出文件的路径配置错误");
            }
            if (!exportFileName.endsWith(".doc")) {
                throw new AlertException("导出文件的文件名配置错误");
            }
            exportFilePath = exportFilePath + exportFileName;
            File outFile = new File(exportFilePath);
            Writer out = null;
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
            t.process(dataMap, out);
            out.close();
        } catch (Exception e) {
            // IOException | TemplateException
            log.error("导出word文档出错", e);
            e.printStackTrace();
            throw e;
        }
        return null;
    }

    /**
     * 将路径中的\替换成/
     *
     * @param path 路径
     * @return
     */
    private String pathReplace(String path) {
        while (path != null && path.contains("\\")) {
            path = path.replace("\\", "/");
        }
        return path;
    }

    /**
     * 判断文件是否存在
     *
     * @param file
     */
    public void checkFileExists(File file) {
        if (file.exists()) {
            log.info("待写入文件存在");
        } else {
            log.info("待写入文件不存在, 创建文件成功");
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 判断文件夹是否存在
     *
     * @param file
     */
    public void checkDirExists(File file) {
        if (file.exists()) {
            if (file.isDirectory()) {
                log.info("目录存在");
            } else {
                log.info("同名文件存在, 不能创建");
            }
        } else {
            log.info("目录不存在，创建目录");
            file.mkdir();
        }
    }


    //本地测试loadType填1，项目路径下获取模板，loadType填非1的数
    public static void main(String[] args) {
        // 导出单个word文档测试
        Map<String, Object> dataMap = new HashMap<>();
        dataMap(dataMap, "");
        String templateFilePath = "F:\\idea-workspace-yx\\serveMasses-workspace\\事项交办单.ftl";
        String exportFilePath = "F:\\idea-workspace-yx\\serveMasses-workspace\\事项交办单.doc";

        Map<String, Object> dataMap2 = new HashMap<>();
        dataMap2(dataMap2);
        String templateFilePath2 = "F:\\idea-workspace-yx\\serveMasses-workspace\\家庭档案信息表.ftl";
        String exportFilePath2 = "F:\\idea-workspace-yx\\serveMasses-workspace\\家庭档案信息表.doc";

        // 测试将多条信息按照一个模板导入一个word中
        Map<String, Object> rows = new HashMap<>();
        List<Map<String, Object>> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Map<String, Object> dataMap1 = new HashMap<>();
            dataMap(dataMap1, "+" + (i + 1));
            list.add(dataMap1);
        }
        rows.put("rows", list);

        String templateFilePath1 = "F:\\idea-workspace-yx\\serveMasses-workspace\\事项交办单格式化.ftl";
        String exportFilePath1 = "F:\\idea-workspace-yx\\serveMasses-workspace\\事项交办单list.doc";
        try {
//            WordExportUtil.getInstance().createDocFile(templateFilePath, dataMap, exportFilePath, 1);
            WordExportUtil.getInstance().createDocFile(templateFilePath1, rows, exportFilePath1, 1);
//            WordExportUtil.getInstance().createDocFile(templateFilePath2, dataMap2, exportFilePath2, 1);
        } catch (Exception e) {
        }
        // 导出多个word文档测试
       /* List<Map<String, Object>> dataMapList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap(dataMap, "+" + i);
            dataMapList.add(dataMap);
        }
        String templateFilePath = "F:\\idea-workspace-yx\\serveMasses-workspace\\事项交办单.ftl";
        String exportFilePath = "F:\\idea-workspace-yx\\serveMasses-workspace\\";
        WordExportUtil wordExportUtil = WordExportUtil.getInstance();
        try {
            for (int i = 0; i < dataMapList.size(); i++) {
                wordExportUtil.createDocFile2(templateFilePath, dataMapList.get(i), exportFilePath, "批量测试" + i + ".doc", 1);
            }
        } catch (Exception e) {
        }*/
    }


    // 45个
    private static void dataMap2(Map<String, Object> dataMap2) {
        dataMap2.put("hzhxm", "张三");//户主姓名
        dataMap2.put("shfzh", "34234234342353454534453");//身份证号
        dataMap2.put("xingbie", "男");//性别
        dataMap2.put("shouji", "1235466566556");//手机号
        dataMap2.put("hunyinzk", "已婚");//婚姻状况
        dataMap2.put("hkszd", "山东省青岛市平度上发顺丰收单法定");//户籍所在地
        dataMap2.put("jtdz", "对方水电费维格瑞特人个人个人个人个人股个地方官的");//家庭地址
        dataMap2.put("xiaoqu", "百通馨苑5区");//小区名
        dataMap2.put("louhao", "28");//所在楼号
        dataMap2.put("dyhao", "1");//所在单元号
        dataMap2.put("shihao", "2301");//所在室号
        dataMap2.put("ifkh", "否");//是否空户
        dataMap2.put("ifzzh", "否");//是否租住户
        dataMap2.put("ifknh", "是");//是否困难户
        dataMap2.put("iftwjr", "否");//是否退伍军人
        dataMap2.put("ifmgh", "是");//是否敏感户
        dataMap2.put("ifjggb", "是");//是否机关机关干部
        dataMap2.put("nqfh", "werwewerw323");//暖气费号
        dataMap2.put("dfh", "233546345");//电费号
        dataMap2.put("sfh", "232352525");//水费号
        dataMap2.put("jtrks", "4");//家庭人口数
        dataMap2.put("lb1", "本人");//类别 本人、配偶、子女等
        dataMap2.put("xm1", "张三");//姓名
        dataMap2.put("zzmm1", "党员");//政治面貌
        dataMap2.put("gzdw1", "机关算法所以呢");//工作单位
        dataMap2.put("lb2", "配偶");//类别
        dataMap2.put("xm2", "杨欣悦");//姓名
        dataMap2.put("zzmm2", "群众");//政治面貌
        dataMap2.put("gzdw2", "上发顺丰");//工作单位
        dataMap2.put("lb3", "父母");//类别
        dataMap2.put("xm3", "张忠信");//姓名
        dataMap2.put("zzmm3", "群众");//政治面貌
        dataMap2.put("gzdw3", "无");//工作单位
        dataMap2.put("lb4", "子女");//类别
        dataMap2.put("xm4", "张天祥");//姓名
        dataMap2.put("zzmm4", "是的发生的");//政治面貌
        dataMap2.put("gzdw4", "afdfas");//工作单位
        dataMap2.put("lb5", "");//类别
        dataMap2.put("xm5", "");//姓名
        dataMap2.put("zzmm5", "");//政治面貌
        dataMap2.put("gzdw5", "");//工作单位
        dataMap2.put("lb6", "");//类别
        dataMap2.put("xm6", "");//姓名
        dataMap2.put("zzmm6", "");//政治面貌
        dataMap2.put("gzdw6", "");//工作单位

    }

    public static void dataMap(Map<String, Object> dataMap, String target) {
        dataMap.put("objyear", "2020");
        dataMap.put("objmonth", "4");
        dataMap.put("objday", "30");
        dataMap.put("objsxbh", "q0001" + target);
        dataMap.put("objtbdw", "人大人大人大人大人大人大");
        dataMap.put("objjmxm", "王二麻子");
        dataMap.put("objxingbie", "男");
        dataMap.put("objjzdz", "长岛县南长山乡34世纪东方长岛县南长山乡34世纪东方长岛县南长山乡34世纪东方");
        dataMap.put("objlxdh", "12345676543");
        dataMap.put("objsxdj", "一般");
        dataMap.put("objqssj", "2020-04-27 09:38:43");
        dataMap.put("objyjjynr", "房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水、" +
                "了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是" +
                "房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是" +
                "房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水、了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是" +
                "房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水、了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是" +
                "房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水、了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是房顶漏水了当但是");
        dataMap.put("objzfgb1", "牟一");
        dataMap.put("objlxdh1", "16789875645");
        dataMap.put("objzfgb2", "张三");
        dataMap.put("objlxdh2", "18989875645");
        dataMap.put("objjbyj", "请住建局处理答复");
        /*dataMap.put("objcljg", "处理结果1处理结果2处理结果3处理结果4" +
                "处理结果5处理结果6处理结果7处理结果8处理结果9" +
                "处理结果1处理结果2处理结果3处理结果5处理结果gf" +
                "处理结果鼎折覆餗处理结果水电费所发生的处理结果发生的范围威风威风方式大V1");// 处理结果*/
        dataMap.put("objdfr", "答疑");
        dataMap.put("objdfsj", "2020-04-30 09:38:43");
        dataMap.put("objdfdh", "17987879986");
        dataMap.put("objifmy", "基本满意");
    }
}
